package com.sean.community.comtroller;

import com.sean.community.annotation.LoginRequired;
import com.sean.community.entity.Comment;
import com.sean.community.entity.DiscussPost;
import com.sean.community.entity.Event;
import com.sean.community.event.EventProducer;
import com.sean.community.service.CommentService;
import com.sean.community.service.DiscussPostService;
import com.sean.community.util.CommunityConstant;
import com.sean.community.util.HostHolder;
import com.sean.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Date;

@Controller
@RequestMapping("/comment")
public class CommentController implements CommunityConstant {
    private CommentService commentService;
    private HostHolder hostHolder;
    private EventProducer producer;
    private DiscussPostService discussPostService;
    private EventProducer eventProducer;
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public void setCommentService(CommentService commentService) {
        this.commentService = commentService;
    }

    @Autowired
    public void setHostHolder(HostHolder hostHolder) {
        this.hostHolder = hostHolder;
    }

    @Autowired
    public void setProducer(EventProducer producer) {
        this.producer = producer;
    }

    @Autowired
    public void setDiscussPostService(DiscussPostService discussPostService) {
        this.discussPostService = discussPostService;
    }

    @Autowired
    public void setEventProducer(EventProducer eventProducer) {
        this.eventProducer = eventProducer;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @LoginRequired
    @RequestMapping(value = "/add/{discussPostId}", method = RequestMethod.POST)
    public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment){
        comment.setUserId(hostHolder.getUser().getId());
        comment.setStatus(0);
        comment.setCreateTime(new Date());
        commentService.addComment(comment);     // 将新评论添加到数据库中
        // 触发评论通知事件
        Event event = new Event()
                .setTopic(TOPIC_COMMENT)                    // 事件主题：评论
                .setUserId(hostHolder.getUser().getId())    // 触发事件的用户：当前登录用户
                .setEntityType(comment.getEntityType())     // 触发事件的实体类型
                .setEntityId(comment.getEntityId())         // 触发事件的实体 id
                .setData("discussPostId", discussPostId);   // 帖子 id： 用于被通知用户可以定位到帖子
        if(comment.getEntityType() == ENTITY_TYPE_DISCUSS_POST){        // 对帖子进行评论
            DiscussPost discussPost = discussPostService.findDiscussPostById(comment.getEntityId());    // 评论的目标帖子
            event.setEntityUserId(discussPost.getUserId());                                             // 帖子的作者
            if (event.getUserId() != event.getEntityUserId()) {         // 对自己的帖子进行评论，不通知
                producer.fireEvent(event);      // 发布消息
            }
            // 对帖子进行评论时触发评论事件：将帖子同步到 es 服务器中
            Event esEvent = new Event()
                    .setTopic(TOPIC_PUBLISH)
                    .setUserId(hostHolder.getUser().getId())
                    .setEntityType(ENTITY_TYPE_DISCUSS_POST)
                    .setEntityId(discussPostId);
            eventProducer.fireEvent(esEvent);

            // 将分数有变化的帖子缓存到 Redis 中，用于计算帖子分数
            String postScoreKey = RedisKeyUtil.getPostScoreKey();
            redisTemplate.opsForSet().add(postScoreKey, discussPostId); // 将帖子 id 缓存到 set 中
        }else if(comment.getEntityType() == ENTITY_TYPE_COMMENT){                           // 对评论进行评论
            Comment targetComment = commentService.findCommentById(comment.getEntityId());  // 目标评论
            event.setEntityUserId(targetComment.getUserId());                               // 目标评论的作者
            if (event.getUserId() != event.getEntityUserId()) {                             // 对自己的评论进行评论，不通知
                producer.fireEvent(event);      // 发布消息
            }
            // 如果是回复某个用户的评论需要再发消息通知该用户
            if(comment.getTargetId() != 0){     // 该评论是对某个用户评论的回复
                event.setEntityUserId(comment.getTargetId());
                if (event.getUserId() != event.getEntityUserId()) {     // 对自己的评论进行回复，不通知
                    producer.fireEvent(event);  // 发布消息
                }
            }
        }
        return "redirect:/discussPost/detail/" + discussPostId;
    }
}
